package com.abl.core.service.sys.impl;


import com.abl.core.common.cache.Cache;
import com.abl.core.common.cache.CacheKey;
import com.abl.core.common.security.AuthUser;
import com.abl.core.common.util.AuthKit;
import com.abl.core.common.util.IdKit;
import com.abl.core.common.util.ObjectKit;
import com.abl.core.common.util.StringKit;
import com.abl.core.domain.db.LkRoleMenu;
import com.abl.core.domain.db.SysMenu;
import com.abl.core.mybatis.mapper.LkRoleMenuMapper;
import com.abl.core.mybatis.mapper.SysMenuMapper;
import com.abl.core.service.sys.SysMenuService;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import static com.abl.core.domain.db.table.LkRoleMenuTableDef.LK_ROLE_MENU;
import static com.abl.core.domain.db.table.SysMenuTableDef.SYS_MENU;


/**
 * 用户表实现
 */
@Slf4j
@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Resource
    private Cache<String> cache;

    @Resource
    private LkRoleMenuMapper roleMenuMapper;

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Override
    public List<SysMenu> allMenuCache() {
        //缓存中有菜单
        String sysMenuStr = cache.get(CacheKey.MENU_SYSTEM_ALL_DATA);

        if (StringKit.isNotBlank(sysMenuStr)) {
            List<SysMenu> menuAllList = JSONArray.parseArray(sysMenuStr, SysMenu.class);
            if (menuAllList.size() > 0) return menuAllList;
        }

        QueryWrapper wrapper = QueryWrapper.create().select("*").from(SYS_MENU)
                .orderBy(SYS_MENU.SORT.asc()).orderBy(SYS_MENU.CT.desc());
        ;
        List<SysMenu> menuAllList = sysMenuMapper.selectListByQuery(wrapper);
        cache.set(CacheKey.MENU_SYSTEM_ALL_DATA, JSONObject.toJSONString(menuAllList));
        return menuAllList;
    }

    public List<SysMenu> userHasMenu() {
        AuthUser currentUser = AuthKit.mastLogin();

        //全部菜单
        List<SysMenu> sysMenus = allMenuCache();

        //root直接返回所有菜单
        if (currentUser.isRoot()) return sysMenus;

        //用户具备的菜单ID
        List<String> roleIds = currentUser.getRoleIds();
        List<String> menuIds = roleMenuMapper.selectObjectListByQueryAs(QueryWrapper.create().select("menu_id").where(LK_ROLE_MENU.ROLE_ID.in(roleIds)), String.class);
        List<SysMenu> userHasMenu = sysMenus.stream().filter(e -> menuIds.contains(e.getId())).toList();
        List<String> list = userHasMenu.stream().map(SysMenu::getTreePath).toList();

        //根据TreePath获取用户全路径菜单
        HashSet<String> haseTreeIds = new HashSet<>();
        list.forEach(e -> {
            haseTreeIds.addAll(JSONArray.parseArray(e).toList(String.class));
        });

        return sysMenus.stream().filter(e -> haseTreeIds.contains(e.getId())).toList();
    }

    @Override
    public boolean insert(SysMenu param) {
        AuthUser authUser = AuthKit.mastLogin();

        param.setId(IdKit.getId());
        if (StringKit.isBlank(param.getPid())) param.setPid("0");

        //遍历树结构
        JSONArray ids = getTreeIds(param.getId(), param.getPid());
        param.setTreePath(ids.toString());

        int i = sysMenuMapper.insertSelective(param);

        //给该角色，添加此菜单的权限
        if (!authUser.isRoot()) {
            addRoleMenu(authUser.getRoleIds(), param.getId());
        }

        //清缓存
        cache.delete(CacheKey.MENU_SYSTEM_ALL_DATA);

        return true;
    }

    //给该角色，添加此菜单的权限
    private void addRoleMenu(List<String> roleIds, String menuId) {
        for (String roleId : roleIds) {
            LkRoleMenu lkRoleMenu = new LkRoleMenu();
            lkRoleMenu.setRoleId(roleId);
            lkRoleMenu.setMenuId(menuId);
            try {
                roleMenuMapper.insert(lkRoleMenu);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public boolean update(SysMenu param) {
        SysMenu sysMenu = ObjectKit.copyToNew(param, "id", "pid", "level", "name", "routePath", "filePath", "type", "sort", "res", "resExclude");

        //遍历树结构
        JSONArray ids = getTreeIds(param.getId(), param.getPid());
        sysMenu.setTreePath(ids.toString());

        int i = sysMenuMapper.update(sysMenu);

        //清缓存
        cache.delete(CacheKey.MENU_SYSTEM_ALL_DATA);

        return true;
    }

    @Override
    public boolean delete(String ids) {
        ArrayList<String> split = StringKit.split(ids);

        int i = sysMenuMapper.deleteBatchByIds(split);

        //清缓存
        cache.delete(CacheKey.MENU_SYSTEM_ALL_DATA);

        return true;
    }

    //根据ID和PID查库，返回树结构JSON数组 ["PID-0","PID-01","自身ID"]
    @Override
    public JSONArray getTreeIds(String nowId, String pid) {
        JSONArray treeIds = new JSONArray();
        treeIds.add(nowId);
        if (!"0".equals(pid)) {
            do {
                QueryWrapper wrapper = new QueryWrapper();
                wrapper.select("id", "pid").from(SysMenu.class).where("id = ?", pid);
                SysMenu sysMenu = sysMenuMapper.selectOneByQuery(wrapper);
                if (sysMenu != null) {
                    pid = sysMenu.getPid();
                    treeIds.add(0, sysMenu.getId());
                }
            } while (pid != null && !pid.equals("0"));
        }
        return treeIds;
    }
}
